package pl.put.to.regression.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class DataSet {
	private static final Pattern WHITESPACES_PATTERN = Pattern.compile("\\s+");

	private List<String> variableNames;
	private String classVariableName;
	private List<DataInstance> instances;

	public DataSet(String dataFilePath) throws IOException {
		variableNames = new ArrayList<String>();
		instances = new ArrayList<DataInstance>();

		File dataFile = new File(dataFilePath);

		if (dataFile.exists() && dataFile.isFile()) {
			readFromFile(dataFile);
		} else {
			throw new IOException("Wrong file path.");
		}
	}

	public int getNumberOfVariables() {
		int result = variableNames.size();

		return result;
	}

	public int getNumberOfInstances() {
		int result = instances.size();

		return result;
	}

	private void readFromFile(File file) throws IOException {
		Reader fileReader = new FileReader(file);
		BufferedReader bufferedReader = new BufferedReader(fileReader);

		try {
			String line = bufferedReader.readLine();
			fillVariableNames(line);

			while ((line = bufferedReader.readLine()) != null) {
				fillVariableValues(line);
			}
		} catch (NumberFormatException e) {
			System.out.println("Some data is not numerical.");
			e.printStackTrace();
		} finally {
			bufferedReader.close();
		}
	}

	private void fillVariableValues(String line) {
		String[] valuesFromFile = WHITESPACES_PATTERN.split(line);

		List<Double> variableValues = new ArrayList<Double>();
		Double classVariableValue = null;

		for (String valueText : valuesFromFile) {
			double value = Double.valueOf(valueText);
			variableValues.add(value);
		}

		classVariableValue = variableValues.remove(variableValues.size() - 1);

		if (variableValues.size() != variableNames.size()) {
			throw new IllegalStateException("Variables count doesn't match.");
		}

		DataInstance instance = new DataInstance(variableNames, classVariableName, variableValues, classVariableValue);
		instances.add(instance);
	}

	private void fillVariableNames(String line) {
		if (line != null) {
			String[] variableNamesFromFile = WHITESPACES_PATTERN.split(line);

			for (String name : variableNamesFromFile) {
				String nameWithoutQuotes = name.replace("\"", "");
				variableNames.add(nameWithoutQuotes);
			}

			classVariableName = variableNames.remove(variableNames.size() - 1);
		}
	}

	public String getClassVariableName() {
		return classVariableName;
	}

	public List<String> getVariableNames() {
		return variableNames;
	}

	public List<DataInstance> getInstances() {
		return instances;
	}
}
